op {
  graph_op_name: "MatrixTriangularSolve"
  in_arg {
    name: "matrix"
    description: <<END
Shape is `[..., M, M]`.
END
  }
  in_arg {
    name: "rhs"
    description: <<END
Shape is `[..., M, K]`.
END
  }
  out_arg {
    name: "output"
    description: <<END
Shape is `[..., M, K]`.
END
  }
  attr {
    name: "lower"
    description: <<END
Boolean indicating whether the innermost matrices in `matrix` are
lower or upper triangular.
END
  }
  attr {
    name: "adjoint"
    description: <<END
Boolean indicating whether to solve with `matrix` or its (block-wise)
         adjoint.

@compatibility(numpy)
Equivalent to scipy.linalg.solve_triangular
@end_compatibility
END
  }
  summary: "Solves systems of linear equations with upper or lower triangular matrices by backsubstitution."
  description: <<END

`matrix` is a tensor of shape `[..., M, M]` whose inner-most 2 dimensions form
square matrices. If `lower` is `True` then the strictly upper triangular part
of each inner-most matrix is assumed to be zero and not accessed.
If `lower` is False then the strictly lower triangular part of each inner-most
matrix is assumed to be zero and not accessed.
`rhs` is a tensor of shape `[..., M, N]`.

The output is a tensor of shape `[..., M, N]`. If `adjoint` is
`True` then the innermost matrices in `output` satisfy matrix equations
`matrix[..., :, :] * output[..., :, :] = rhs[..., :, :]`.
If `adjoint` is `False` then the strictly then the  innermost matrices in
`output` satisfy matrix equations
`adjoint(matrix[..., i, k]) * output[..., k, j] = rhs[..., i, j]`.

Note, the batch shapes for the inputs only need to broadcast.

Example:
```python

a = tf.constant([[3,  0,  0,  0],
                 [2,  1,  0,  0],
                 [1,  0,  1,  0],
                 [1,  1,  1,  1]], dtype=tf.float32)

b = tf.constant([[4],
                 [2],
                 [4],
                 [2]], dtype=tf.float32)

x = tf.linalg.triangular_solve(a, b, lower=True)
x
# <tf.Tensor: shape=(4, 1), dtype=float32, numpy=
# array([[ 1.3333334 ],
#        [-0.66666675],
#        [ 2.6666665 ],
#        [-1.3333331 ]], dtype=float32)>

# in python3 one can use `a@x`
tf.matmul(a, x)
# <tf.Tensor: shape=(4, 1), dtype=float32, numpy=
# array([[4.       ],
#        [2.       ],
#        [4.       ],
#        [1.9999999]], dtype=float32)>
```
END
}
